using System;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Locations.API.Infrastructure.AuthExtension.TestAuth
{
    public static class TestAuthenticationExtensions
    {
        /// <summary>
        /// 构造ClaimsIdentity
        /// </summary>
        /// <param name="claims"></param>
        /// <returns></returns>
        private static ClaimsIdentity BuildIdentity(Claim[] claims)
        {
            ClaimsIdentity identity;
            if (claims == null)
            {
                identity = new ClaimsIdentity(new Claim[]
               {
                    new Claim(ClaimTypes.Name, Guid.NewGuid().ToString()),
               }, "test");
            }
            else
            {
                identity = new ClaimsIdentity(claims, "test");
            }

            return identity;
        }

        /// <summary>
        /// 注册测试Authentication
        /// </summary>
        /// <param name="services"></param>
        /// <param name="claims"></param>
        /// <returns></returns>
        private static AuthenticationBuilder ConfigureTestAuth(this IServiceCollection services, Claim[] claims)
        {
            var identity = BuildIdentity(claims);
            return services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = "Test Scheme"; // has to match scheme in TestAuthenticationExtensions
                options.DefaultChallengeScheme = "Test Scheme";
            }).AddTestAuth(o => { o.Identity = identity; });
        }

        /// <summary>
        /// 非生成环境免登（AddAuthentication）
        /// </summary>
        /// <param name="services"></param>
        /// <param name="env"></param>
        /// <param name="claims"></param>
        /// <returns></returns>
        public static AuthenticationBuilder ConfigureAuth(this IServiceCollection services, IHostingEnvironment env, Claim[] claims = null)
        {
            return env.IsProduction() == true ? services.AddAuthentication() : services.ConfigureTestAuth(claims);
        }

        /// <summary>
        /// 非生成环境免登（指定scheme）
        /// </summary>
        /// <param name="services"></param>
        /// <param name="env"></param>
        /// <param name="scheme"></param>
        /// <param name="claims"></param>
        /// <returns></returns>
        public static AuthenticationBuilder ConfigureAuth(this IServiceCollection services, IHostingEnvironment env, string scheme, Claim[] claims = null)
        {
            return env.IsProduction() == true ? services.AddAuthentication(scheme) : services.ConfigureTestAuth(claims);
        }

        /// <summary>
        /// 非生成环境免登(自定义注册)
        /// </summary>
        /// <param name="services"></param>
        /// <param name="env"></param>
        /// <param name="configuration"></param>
        /// <param name="customAuth"></param>
        /// <param name="claims"></param>
        public static void ConfigureAuth(this IServiceCollection services, IHostingEnvironment env, IConfiguration configuration, Action<IConfiguration> customAuth, Claim[] claims = null)
        {
            if (env.IsProduction())
            {
                customAuth(configuration);
            }
            else
            {
                services.ConfigureTestAuth(claims);
            }
        }

        /// <summary>
        /// 注册scheme和handle
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="configureOptions"></param>
        /// <returns></returns>
        public static AuthenticationBuilder AddTestAuth(this AuthenticationBuilder builder, Action<TestAuthenticationOptions> configureOptions)
        {
            return builder.AddScheme<TestAuthenticationOptions, TestAuthenticationHandler>("Test Scheme", "Test Auth", configureOptions);
        }
    }
}
